﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using AutoFillCenter;
using android.bluebox.model;


namespace FillServiceForm
{
    class MessageDispatcher
    {        
        private const int _capacity = 10;
        //private String[] _messageQueue = new String[10];
        private Queue<String> _messages = null;

        private ClientInfo _mobileInfo;        
        
        public Queue<String> Messages
        {
            get { return _messages; }
            set { _messages = value; }
        }

        public MessageDispatcher(){
            _messages = new Queue<String>(_capacity);
        }

        public MessageDispatcher(ClientInfo info)
        {
            _mobileInfo = info;
            if (info == null)
                _mobileInfo = new ClientInfo();
            _messages = new Queue<String>(_capacity);
        }

        

        public String runImmediately(String str,Socket handler, ClientInfo info)
        {
            byte[] msg = null;
            System.Diagnostics.Debug.WriteLine(str);

            // remove <EOF>
            str = str.Replace("<EOF>", "");
            String[] messageData = str.Split(Constant.SEPERATOR_CHAR);            
            String pairCode = messageData[0].ToUpper();
            int requestTypeMessage = 0;
            int responseTypeMessage = 0;
            String data = "";
            String message = "";
            String ss = "";            

            try
            {
                requestTypeMessage = int.Parse(messageData[1]);
            }
            catch (FormatException ex)
            {
                System.Diagnostics.Debug.WriteLine("Can not cast to int");
                return "-1";
            }
            

            /**
             * TEST SERVER. SERVER MUST RESPONSE
             */            
            if (requestTypeMessage == Constant.REQUESTWELCOME)
            {
                ss = Constant.SEPERATOR_CHAR + Constant.WELCOMECONNECTING.ToString();
                msg = Encoding.UTF8.GetBytes(ss);
                _mobileInfo.LastConnect = DateTime.Now;
                IPEndPoint remoteIpEndPoint = handler.RemoteEndPoint as IPEndPoint;
                
                handler.Send(msg);
                return "0" + Constant.SEPERATOR_CHAR + remoteIpEndPoint.Address.ToString();
            }

            if (_mobileInfo.Status != Constant.STATUS_CONNECTED)
            {
                if (requestTypeMessage == Constant.REQUESTCONNECTING)
                {
                    _mobileInfo.CodeValidation = Util.RandomString(Constant.CONFIG_NUM_RAND_STRING);
                    _mobileInfo.Status = Constant.STATUS_WAIT_FOR_CODE;
                    _mobileInfo.LastConnect = DateTime.Now;
                    responseTypeMessage = Constant.RESPONSECONNECTING;
                    message = _mobileInfo.CodeValidation;                    
                }
                else if (_mobileInfo.Status == Constant.STATUS_WAIT_FOR_CODE && requestTypeMessage == Constant.REQUESTPAIRCODE)
                {
                    String md5_code = Crypto31.createMD5(_mobileInfo.CodeValidation);
                    if ( md5_code == messageData[2])
                    {
                        _mobileInfo.Status = Constant.STATUS_CONNECTED;
                        IPEndPoint remoteIpEndPoint = handler.RemoteEndPoint as IPEndPoint;
                        _mobileInfo.Ip = remoteIpEndPoint.Address.ToString();
                        _mobileInfo.LastConnect = DateTime.Now;                        
                        System.Diagnostics.Debug.WriteLine(_mobileInfo.Ip);
                        
                        responseTypeMessage = Constant.RESPONSEPAIRCODE;
                        message = _mobileInfo.Ip.ToString();
                        Crypto31.createInstance(md5_code);
                        _mobileInfo.Id = (new Random()).Next().ToString();
                    }
                }
            }
            else
            {  
                
                if (pairCode != _mobileInfo.CodeValidation )
                {
                    return "-1" + Constant.SEPERATOR_CHAR + "Wrong validation";
                }
                _mobileInfo.LastConnect = DateTime.Now;
                if (requestTypeMessage == Constant.REQUESTFIELD)
                {
                    responseTypeMessage = Constant.RESPONSEFIELD;
                    // Send message to mobile to get info

                    //ClientSender sender = new ClientSender();
                    //ClientSender.SendMessage("");

                    
                    for (int i = 2; i < messageData.Length; i++)
                    {
                        data += Constant.SEPERATOR_CHAR + messageData[i];
                    }
                    
                }
                                                                 
                if (DateTime.Now.Subtract(_mobileInfo.LastConnect).TotalMinutes > Constant.TIMEOUT)
                {
                    _mobileInfo.CodeValidation = Util.RandomString(Constant.CONFIG_NUM_RAND_STRING);
                    _mobileInfo.Status = Constant.STATUS_WAIT_FOR_CODE;
                    System.Diagnostics.Debug.WriteLine("TIMEOUT HERE :"+DateTime.Now.TimeOfDay + "_"+_mobileInfo.LastConnect.TimeOfDay);
                    responseTypeMessage = Constant.RESPONSECONNECTING;
                    //message = _mobileInfo.CodeValidation;
                    
                    //message = "," + _mobileInfo.CodeValidation;                    
                }
                 
                if (requestTypeMessage == Constant.RESPONSECONTENT)
                {
                    AutoFill autoFill = AutoFillFactory.getAutoFill(messageData[2]);
                    autoFill.Fill(messageData[3],null);
                }
            }
    

            // do response here            
            ss = _mobileInfo.Id + Constant.SEPERATOR_CHAR + responseTypeMessage + data;
            if (_mobileInfo.Status == Constant.STATUS_CONNECTED && _mobileInfo.CodeValidation != null)
            {
                ss = Crypto31.encrypt(ss);
            }

            msg = Encoding.UTF8.GetBytes(ss);            
            handler.Send(msg);
            
            
            System.Diagnostics.Debug.WriteLine(ss);
            Console.WriteLine(ss);
            return requestTypeMessage.ToString() + Constant.SEPERATOR_CHAR + message;
        
            //return null;
        }

        public String processMessage(String str,Socket handler, ClientInfo info)
        {
            return null;
        }

        public void dispatch(String str)
        {           
 
        }
    }
}
